Inhalt: Hier wird beschrieben, wie die mit Prprozessorkommandos versehenen
        Quelltexte in Modula-Quelltexte konvertiert werden.
        Dieser Text sollte in aller Ruhe von Anfang bis Ende durchgelesen
        werden, bevor irgendetwas mit dem Prprozessor angestellt wird!
        Danach sollte der fr den verwendeten Compiler geeignete Abschnitt
        in COMPILER.TXT gelesen werden.


Einleitung
==========

Wie bereits in M2LIB.TXT angedroht, kommt man nicht umhin mit einem
Kommandointerpreter (Shell) zu arbeiten, um die Bibliotheksmodule
in ein fr den Modula-Compiler verstndliches Format zu bringen.

Zuerst einmal: Es wird hier weder erklrt, wie man eine Shell installiert,
noch wie man sie bedient. Beides mu ich als bekannt voraussetzen. Wem das
nicht reicht, kann mir immer noch eine Diskette schicken, um die bereits
prprozessierten Quelltexte zu erhalten. Nheres dazu in M2LIB.TXT.

Davon abgesehen sollten die folgenden Informationen ausreichen, um sowohl
mit den Shells zurechtzukommen, fr die bereits Script-Dateien zum
Prprozessieren beiliegen, als auch eigene Scripts fr andere Shells zu
erstellen, wobei die vorhandenen als Vorbild dienen knnen.

Jeder Quelltext der Bibliothek mu einzeln mit dem Prprozessor bearbeitet
werden. Prinzipiell wre es natrlich mglich, per Hand den Prprozessor
fr jede Datei aufzurufen und dabei mit den ntigen Parametern zu versorgen;
das kann man aber bei rund 200 Dateien niemandem zumuten. Aus diesem Grund
wird das ganze mit Hilfe eines Shell-Scripts (auch als Batch-Datei bekannt)
automatisiert. Dabei kann dann auch bercksichtigt werden, da die Quelltexte
auf mehrere Unterverzeichnisse verteilt sind.

Es folgen zuerst allgemeine Erluterungen zum Aufruf des Prprozessors und
der Konvertierung eines einzelnen Quelltextes. Diese Beschreibung gilt
unabhngig von der verwendeten Shell. Danach wird der Umgang mit den
vorhandenen Shell-Scripts erklrt.


Prprozessieren einer Datei
===========================

Verwendete Environmentvariablen
-------------------------------

Zuerst einmal mssen die Programme 'cpp.ttp' und 'x2d1.tos' in ein
Verzeichnis kopiert werden, das in der Environmentvariable PATH erwhnt ist,
denn in diesen Verzeichnissen sucht die Shell nach ausfhrbaren Dateien.
Ist das erledigt, knnen die Programme einfach durch Nennung des Dateinamens
(ohne Extension) gestartet werden.

Der Prprozessor bentigt noch die Environmentvariable GNUINC, die ein
oder mehrere Verzeichnisse enthlt, in der Dateien gesucht werden, die mit
dem Befehl: #include eingebunden werden sollen. Das wird fr den Quelltext
OSCALLS.IPP bentigt, in dem die Datei OSCALLS.M2H geladen wird. Enthlt
GNUINC mehrere Verzeichnisse, z.B. eins fr die Modula-2-Header (*.M2H)
und eins fr die C-Header (*.H, der Prprozessor gehrt ja eigentlich zum
GNU-C-Compiler, und ich benutze ihn fr beides), werden die Verzeichnisse
durch Kommata (evtl. funktionieren auch Semikola) getrennt; auerdem knnen
die Pfade, unabhngig von der verwendeten Shell, in der gewohnten DOS-
Notation mit Laufwerk und \ angegeben werden, da die Variable nur vom
Prprozessor ausgewertet wird.

OSCALLS.M2H mu also in dieses bzw. eins dieser Verzeichnisse kopiert werden.
Es ist sinnvoll, auch die Datei PORTAB.M2H in dieses Verzeichnis zu kopieren,
obwohl sie auch woanders stehen knnte.

Die Environmentvariable TMPDIR wird nur bentigt, wenn die Shell keine Pipes
beherrscht und deswegen Zwischendateien angelegt werden mssen. TMPDIR
enthlt das Verzeichnis, in dem die Zwischendatei angelegt werden kann.


Aufruf des Prprozessors
------------------------
Der grundlegende Aufruf des Prprozessors aus einer Shell heraus lautet:

  cpp -undef -P -D<compiler> -imacros <portab.m2h> <infile> <outfile>


Die Bedeutung der Parameter im Einzelnen:

  -undef    Es soll keine vordefinierten Nicht-Standardmakros (z.B.
            atarist) geben.

  -P        Normalerweise produziert der Prprozessor einige Zeilen mit
            Hilfsinformationen fr den C-Compiler. Diese mssen unterdrckt
            werden.

  -D        Mit der Option -D kann ein Makro definiert werden. Hier
            wird es dazu benutzt den Compiler zu identifizieren,
            z.B. durch -DLPRM2

  -imacros  Hiermit wird eine Makrodatei eingelesen, wobei nur die
            Definitionen bernommen werden, jedoch keine Ausgabedatei
            erzeugt wird. Das wird benutzt, um die Makrodatei PORTAB.M2H,
            die alle compilerspezifischen Definitionen enthlt, einzulesen,
            z.B. mit:

              -imacros e:\usr\include\m2\portab.m2h

  <infile>  Das ist die Datei, die durch den Prprozessor bearbeitet werden
            soll, z.B.: oscalls.dpp. Ist keine Eingabedatei angegeben,
            liest der Prprozessor von der Standardeingabe.

  <outfile> Das ist die Ausgabedatei, die aus <infile> vom Prprozessor
            erzeugt wird, z.B. oscalls.def. Ist keine Ausgabedatei angegeben,
            schreibt der Prprozessor auf die Standardausgabe.


Die Ausgabedatei <outfile> enthlt noch eine ganze Menge Leerzeilen, die
durch das Expandieren der Makros entstanden sind. Die Zeilenenden sind
auerdem nach UNIX-Konvention nur mit LF statt CR+LF abgeschlossen.
Deshalb wird die Ausgabedatei noch mit dem Programm x2d1 bearbeitet,
das aufeinanderfolgende Leerzeilen zu einer komprimiert und auerdem
fr die richtigen Zeilenenden sorgt. Der Aufruf dieses Programms ist
einfach:

  x2d1 < <in> > <out>

D.h. es ist ein sogenannter Filter, der von der Standardeingabe liest
und in die Standardausgabe schreibt. Wenn die verwendete Shell
die sog. Pipelines beherrscht, knnen die beiden Programme durch eine
Pipe (-> |) verbunden werden, wodurch die Ausgabe des Prprozessors direkt
mit der Eingabe von x2d1 verbunden wird. Beherrscht die Shell dies nicht,
mu eine Zwischendatei angelegt werden.


Benutzung der Shells Mupfel, Ksh und Bash
=========================================

Die folgenden Abschnitte beziehen sich auf die Shells:

Mupfel, Version >= 1.9999 (aus GEMINI)

Ksh,    Version >= 4.8/1.1

Bash,   Version >= 1.14.0

Ich habe nur diese Versionen getestet. Es ist sehr wahrscheinlich, da ltere
Versionen nicht ohne nderungen der Scripts funktionieren. Alle diese
Shells gibt es auf diversen ftp-Servern, wobei die Mupfel aus der GEMINI-
Distribution wohl am verbreitetsten ist.

Alle drei Shells verwenden so ziemlich dieselbe Syntax in Shell-Scripts
(erweiterte Bourne-Shell-Syntax, nach POSIX.2), deshalb sind die Scripts
zum Prprozessieren auch fast identisch. Unterschiede ergeben sich nur an
wenigen Stellen durch kleinere Fehler oder Inkompatibilitten (der Shells).

Whrend die Mupfel speziell auf den Atari zugeschnitten ist und sowohl
unter normalem TOS als auch MiNT/MultiTOS luft (allerdings ohne Job-Control),
sind Ksh und Bash von Unix portierte Shells, die MiNT/MultiTOS bentigen.
Ein groes Problem ist es immer wieder, einer solchen Shell beizubringen, die
eigenen Shell-Scripts nicht nur zu finden, sondern auch als ausfhrbar zu
akzeptieren, wenn alleine der Name angegeben wird, genauso als wre es ein
normales Programm. Je nach Shell und/oder Version sind einige oder alle der
folgenden Manahmen notwendig:

1) Das Shell-Script mu sich in einem Verzeichnis befinden, das in PATH
   erwhnt ist, denn in diesen Verzeichnissen sucht die Shell nach
   ausfhrbaren Dateien.

2) Es kann sein, da die Shell die eigenen Scripts an bestimmten Endungen
   erkennt; dann wird an den Dateinamen z.B. noch ein .mup oder .ksh
   angehngt, was aber beim Aufruf nicht angegeben zu werden braucht.

3) Die erste Zeile des Scripts sollte mit den Zeichen #! beginnen, auf die
   direkt der Name der Shell folgt. Je nach Shell kann es auch erforderlich
   sein den vollen Pfadnamen anzugeben.

4) Wenn das Script auf einem entsprechenden Dateisystem liegt, z.B. einer
   Minix-Partition, sollte das x-Bit gesetzt werden (chmod +x <script>),
   mit dem ausfhrbare Dateien gekennzeichnet werden knnen (was aber
   nicht heit, da sie tatschlich ausfhrbar sind; ob dem so ist,
   wird erst beim Laden der Datei festgestellt).

Wenn das alles nichts hilft, kann man das Script mit vollstndigem Pfad
als Argument eines expliziten Aufrufs der Shell angeben, z.B.:

  ksh /bin/m2pp.ksh <Parameter von m2pp.ksh>


Bei mir sind folgende Manahmen ntig, um das Prprozessor-Script mit dem
Aufruf: m2pp starten zu knnen:

o Gemeinsamkeiten:
  - Fr alle drei Shells gilt 1).
  - Fr keine der drei Shells ist 4) ntig, schadet aber auch nichts.
  - Environmentvariablen werden mittels export <Variable>=<Wert> angelegt.
    Fr den Prprozessor z.B.:
      export GNUINC="e:\usr\include\m2,e:\usr\include"
  - Die Environmentvariable TMPDIR wird nicht bentigt, da alle drei Shells
    Pipes beherrschen.

o Mupfel:
  zu 2): Scriptdateien werden an der Endung .mup erkannt, deswegen heit das
         Script m2pp.mup. Wenn man GEMINI auspackt, wird auch ein Verzeichnis
         SCRIPTS angelegt -- m2pp.mup kann dorthin kopiert werden.

  zu 3): Als erste Zeile ist '#!mupfel' erforderlich. Der Pfad der Mupfel
         braucht nicht angegeben zu werden.

  Die Pfade in PATH werden in DOS-Notation angegeben, also mit \ als
  Verzeichnistrenner und einer Laufwerksangabe. Die Pfade werden durch
  Kommata oder Semikola getrennt. Beispiel:

    export PATH=".;e:\bin;e:\usr\bin"


o Ksh:
  zu 2): Scriptdateien werden an der Endung .ksh erkannt, deswegen heit
         das Script m2pp.ksh.

  zu 3): Als erste Zeile ist der vollstndige Pfad der Ksh erforderlich,
         also z.B. #!/bin/ksh.

  Die Pfade in PATH werden in UNIX-Notation angegeben, also mit / als
  Verzeichnistrenner. Eine Laufwerksangabe ist nur in der Form /dev/e/
  (fr e:\) mglich, sinnvoller ist es jedoch Laufwerk U: als Wurzel zu
  verwenden und in MINT.CNF symbolische Links auf die ``realen''
  Verzeichnisse anzulegen, so da alle Pfade mit / beginnen knnen. Die
  Pfade werden UNIX-like durch den Doppelpunkt getrennt. Beispiel:

    export PATH=".:/bin:/usr/bin"

  WICHTIG: Das Script ist eine Textdatei im UNIX-Format, d.h. die Zeilen-
           enden werden durch LF reprsentiert, nicht durch CR+LF. Bei
           falschen Zeilenenden meldet Ksh Syntaxfehler.


o Bash:
  zu 2): Es gibt keine spezielle Extension fr Script-Dateien, deshalb
         heit das Script einfach m2pp.

  zu 3): Als erste Zeile reicht ein #!bash. Der Pfad braucht nicht angegeben
         zu werden

  Fr die Pfade in PATH gilt das gleiche wie bei der Ksh.

  WICHTIG: Das Script ist eine Textdatei im UNIX-Format, d.h. die Zeilen-
           enden werden durch LF reprsentiert, nicht durch CR+LF. Bei
           falschen Zeilenenden meldet Bash Syntaxfehler.


Wie schon gesagt, ist das Script bei allen drei Shells fast identisch. Im
folgenden werde ich von der Mupfel-Version ausgehen, was aber kaum einen
Unterschied macht (Pfade werden unterschiedlich angegeben).


Die Benutzung von m2pp
----------------------

Als erstes mssen/knnen in der Datei noch einige wenige Dinge an die
verwendete Umgebung angepat werden. Dazu wird gleich am Anfang des Scripts
die Funktion setup() definiert, in der diese Anpassungen durch Setzen von
Shell-Variablen vorgenommen werden.

Im einzelnen:

o Die Variable def_macros mu auf den vollstndigen Pfad der Makrodatei
  PORTAB.M2H gesetzt werden. Beispiel:

    def_macros=e:\usr\include\m2\portab.m2h

o Je nach Compiler haben die Quelltexte unterschiedliche Extensionen fr
  Definitions-, Implementations- und Programmodule. Welche das sind, wird
  zur Laufzeit anhand des verwendeten Compilers bestimmt, indem die Variablen
  m2_def, m2_imp und m2_mod auf die entsprechenden Werte gesetzt werden.
  Diese Extensionen stimmen bereits fr alle Systeme in Standardkonfiguration.
  Bei einigen Systemen (HM2, MM2) kann man sie jedoch ndern, und dann mu
  das ebenfalls in m2pp gendert werden. Normalerweise ist es aber unntig.

o Weiterhin kann man festlegen, welche Extensionen die Ursprungsquelltexte
  mit den Prprozessorkommandos haben. Dies sind normalersweise dpp, ipp
  und mpp, so da man auch hier nichts ndern mu. Falls man andere
  Endungen verwenden mchte, mssen die Variablen cpp_def, cpp_imp und
  cpp_mod entsprechend gesetzt werden.

Erforderlich ist i.allg. also nur das Setzen von def_macros.
Beim Bash-m2pp und Ksh-m2pp.ksh mu man unbedingt darauf achten, da die
Zeilenenden nur aus LF bestehen, wenn man die Datei abspeichert!


Ruft man das Script mit: m2pp -h (fr Hilfe) auf, erscheint folgender Text:

  Aufruf: m2pp [OPTIONEN] compiler destdir

   -d dir         Alle Dateien im Verzeichnis <dir>
   -s dir         Alle Dateien in allen Unterverzeichnissen von <dir>
   -f file        Nur Datei <file>
   -m macros      <macros> statt des Default-PORTAB.M2H benutzen
   -q             Keine Meldungen auer denen des Prprozessors
   -h             Dieser Text

  M2-Dateien mit Prprozessorkommandos werden in reine M2-Dateien
  umgewandelt.
  Fr <compiler> kann eine der folgenden Konstanten angegeben werden:
  LPRM2, SPCM2, TDIM2, MM2, HM2.
  Die Optionen -s, -d und -f schlieen sich gegenseitig aus. Ohne eine
  dieser Optionen werden alle Dateien im aktuellen Verzeichnis bearbeitet.
  Optionen drfen nicht gruppiert werden und Argumente mssen von der
  Option durch ein Leerzeichen getrennt sein.


Daraus ergibt sich bereits die Anwendung. Angenommen, M2LIB wurde im Wurzel-
verzeichnis von Laufwerk e: ausgepackt, die Modula-2-Dateien sollen im
Verzeichnis m2lib auf dem Laufwerk m: landen und das ganze soll fr den
LPR-Compiler erzeugt werden, dann fhren folgende Schritte zum Ziel:

Prprozessieren der POSIX-Module mit:

  m2pp -s e:\m2lib\source\posix LPRM2 m:\m2lib

Entsprechend fr die ISO-Module:

  m2pp -s e:\m2lib\source\iso LPRM2 m:\m2lib

Die Module aus MISC befinden sich nicht in Unterverzeichnissen:

  m2pp -d e:\m2lib\source\misc LPRM2 m:\m2lib

Wie gegen Ende dieses Textes unter 'Tips' erlutert, sollte man jedoch nicht
alle Dateien auf einmal prprozessieren, sondern jede Bibliothek erst
bersetzen, bevor man mit der nchsten beginnt.

Mchte man eine einzelne Datei prprozessieren, wie es z.B. fr den LPR-
Compiler beim Modul 'DosSystem' erforderlich ist, ist ein Aufruf der folgenden
Art geeignet:

  m2pp -f e:\m2lib\source\posix\dossyste.ipp LPRM2 m:\


Ensprechend den Bibliotheken knnen auch die Testmodule prprozessiert
werden, die sich nicht in Unterverzeichnissen befinden:

  m2pp -d e:\m2lib\test\posix LPRM2 m:\m2lib
  m2pp -d e:\m2lib\test\iso LPRM2 m:\m2lib
  m2pp -d e:\m2lib\test\misc LPRM2 m:\m2lib

Weitere Optionen von m2pp knnen bei Bedarf ausprobiert werden. Das Script
nimmt, soweit mglich, Sicherheitsabfragen vor, so da auch Fehlermeldungen
erscheinen knnen, die aber selbsterklrend sind.


Benutzung der Shell Gulm
=========================

Diese Shell ist zwar schon seit langem nicht mehr Stand der Technik, trotzdem
wird sie aber wohl noch von vielen benutzt (von mir auch, jedenfalls
manchmal), weil sie eine der ersten war, die ein gewisses ``UNIX-Feeling''
aufkommen lie.

Die Script-Dateien sind so simpel wie mglich gehalten. Von der Shell werden
lediglich die Fhigkeiten Script-Dateien mit Parametern aufzurufen (auch aus
anderen Script-Dateien heraus), Ein- und Ausgabe umzulenken und Environment-
variablen anzulegen, verwendet. Das hat den Vorteil, da man die Scripts
an praktisch jede andere Shell anpassen kann, andererseits entfllt
jegliche Sicherheitsabfrage, so da man beim Aufruf der Scripts leicht etwas
falsch machen kann (einmal nicht aufgepat und schon ist ein Quelltext
futsch -- ist mir schon passiert!).

Ausfhrbare Scripts werden an der Endung .g erkannt und mssen in einem
Verzeichnis stehen, das in PATH erwhnt ist. Gestartet werden sie ohne
Angabe der Endung. Im Gegensatz zu den oben beschriebenen UNIX-Shells werden
Scripts nicht von jeweils einer eigenen Instanz der Shell ausgefhrt, sondern
immer nur von der einen existierenden. Deshalb knnen Scripts auch
geschachtelt werde, ohne da dabei nennenswert Speicher ``verbraucht'' wird.
Im Verzeichnis BIN\GULAM befinden sich eine Menge Scripts, die zwar nicht
alle bentigt werden, fr's erste sollten sie jedoch am besten in ein
separates Verzeichnis kopiert werden, das dann in PATH erwhnt wird.

Die folgenden Variablen werden am besten in der Startup-Datei GULAM.G
gesetzt:

  set path '.,e:\usr\bin,e:\bin'

Nach einem 'set path' wird bei Gulm automatisch die Environmentvariable
PATH gesetzt. Die richtigen Pfade sind natrlich dem eigenen System
anzupassen.

Environmentvariablen werden mit dem Befehl setenv <Variable> <Wert> gesetzt.
Fr GNUINC sieht das dann z.B. so aus:

  setenv GNUINC e:\usr\include\m2,e:\usr\include

Da Gulm keine Pipes beherrscht, mu auch TMPDIR gesetzt werden, z.B.:

  setenv TMPDIR e:\tmp


Wie schon gesagt, lassen sich die Scripts relativ einfach schachteln, was
ich auch ausgenutzt habe. Das ``Kern-Script'' ist m2ppx.g, das lediglich
einen einzelnen Quelltext prprozessiert und dabei die am Anfang dieser Datei
beschriebenen Befehle verwendet. Der Aufruf lautet:

  m2ppx <compiler> <infile> <outfile>

Dabei identifiziert <compiler> den verwendeten Compiler und kann einer der
folgenden Bezeichner sein: LPRM2, HM2, MM2, TDIM2, SPCM2.
<infile> ist die mit Prprozessorkommandos versehene Eingabedatei und
<outfile> ist der erzeugte Modula-Quelltext.
In diesem Script mu noch der Pfad fr die Makrodatei PORTAB.M2H angepat
werden, z.B.:

  -imacros e:\usr\include\m2\portab.m2h


Dieses Script kann dazu verwendet werden, eine einzelne Datei zu
prprozessieren, z.B. das fr den LPR-Compiler zustzlich bentigte
'DosSystem':

  m2ppx LPRM2 e:\m2lib\source\posix\dossyste.ipp m:\dossyste.mod

Um jedoch mehrere Dateien auf einmal zu konvertieren, mu dieses Script
automatisch fr alle gewnschten Dateien aufgerufen werden. Dafr sind die
Scripts x_m2.g, iso_m2.g, misc_m2.g, tx_m2.g, tiso_m2.g und tmisc_m2.g
zustndig.

Mit den ersten drei Scripts werden jeweils die Bibliotheken prprozessiert,
whrend die anderen drei fr die Testmodule zustndig sind.
Fr alle diese Scripts ist es wichtig, da man zuerst in das Oberverzeichnis
der jeweiligen Bibliothek wechselt, bevor das Script aufgerufen wird, also
z.B. mu das aktuelle Verzeichnis ...\SOURCE\POSIX sein, wenn man x_m2
aufruft, und ...\TEST\POSIX, wenn man tx_m2 aufruft!

Die Parameter fr die Bibliotheksscripts:

  *_m2 <compiler> <destdir> <def-ext> <imp-ext>

Die Parameter fr die Testscripts:

  *_m2 <compiler> <destdir> <mod-ext>

<destdir> ist das Verzeichnis, in dem die konvertierten Module landen sollen,
<def-ext> ist die Extension fr Definitionsmodule, <imp-ext> ist die
Extension fr Implementationsmodule und <mod-ext> ist die Extension fr
Programmodule.

Angenommen, M2LIB wurde im Wurzelverzeichnis von Laufwerk e: ausgepackt,
die Modula-2-Dateien sollen im Verzeichnis m2lib auf dem Laufwerk m: landen
und das ganze soll fr den LPR-Compiler erzeugt werden, dann fhren folgende
Schritte zum Ziel:

  cd e:\m2lib\source\posix
  x_m2 LPRM2 m:\m2lib def mod

  cd e:\m2lib\source\iso
  iso_m2 LPRM2 m:\m2lib def mod

  cd e:\m2lib\source\misc
  misc_m2 LPRM2 m:\m2lib def mod

fr die Bibliotheksmodule, und

  cd e:\m2lib\test\posix
  tx_m2 LPRM2 m:\m2lib mod

  cd e:\m2lib\test\iso
  tiso_m2 LPRM2 m:\m2lib mod

  cd e:\m2lib\test\misc
  tmisc_m2 LPRM2 m:\m2lib mod

fr die Testmodule.

Wie gegen Ende dieses Textes unter 'Tips' erlutert, sollte man jedoch nicht
alle Dateien auf einmal prprozessieren, sondern jede Bibliothek erst
bersetzen, bevor man mit der nchsten beginnt.

Wenn man sich die Angabe der Parameter bei diesen Scripts ersparen bzw. eine
potentielle Fehlerquelle ausschlieen will, kann man sich weitere Scripts
schreiben, die einfach nur aus dem Aufruf mit geeigneten Parametern bestehen.

Ein Script zum Prprozessieren der POSIX-Module fr LPR knnte z.B. so
aussehen:

    Name: XLPR.G
  Inhalt: x_m2 LPRM2 m:\m2lib def mod

Genau diese Aufgabe haben all' die anderen Script-Dateien in BIN\GULAM. Sie
dienen jedoch nur als Beispiel, mindestens der Ausgabepfad mu an die
eigenen Verhltnisse angepat werden. Aus den Namen dieser Scripts ist
jeweils ersichtlich (bzw. sollte ersichtlich sein), fr welchen Compiler
und welche Bibliothek sie gedacht sind.


ndern der Konfiguration
========================

In der Datei PORTAB.M2H knnen einige Einstellungen vorgenommen werden,
die den erzeugten Modula-Quelltext global beeinflussen, indem bestimmte
Compileroptionen gesetzt werden. Hierzu werden gleich am Anfang der Datei
folgende Makros definiert:

  #if 0
  #define __RES_ON_STACK__
  #endif

  #if 1
  #define __LONG_WHOLE__
  #endif

  #if 0
  #define __LONG_REAL__
  #endif

  #if 1
  #define __REG_VARS__
  #endif

  #if 0
  #define __RANGE_CODE__
  #endif

  #if 0
  #define __STACK_CODE__
  #endif

  #if 0
  #define __DEBUG_CODE__
  #endif

Die Einstellung dieser Makros kann auf Wunsch verndert werden. Dargestellt
ist die Defaulteinstellung. Falls die Bedingung im umgebenden #if gleich 0
ist, ist das Makro undefiniert und damit ausgeschaltet, sonst ist es
eingeschaltet. Falls die entsprechende Option bei einem Compiler nicht
einstellbar ist, hat das Makro keine Bedeutung. Falls die Option nur vor
dem Start des Compilers in einem Optionendialog aber nicht im Quelltext
einstellbar ist, mu(!) dieses Makro mit der globalen Compilereinstellung
bereinstimmen. Falls die Option dagegen im Quelltext gesetzt werden kann,
wird sie automatisch, zusammen mit anderen Grundeinstellungen, abhngig von
diesem Makro gesetzt.

Die Bedeutung der Makros ist wie folgt:

  __RES_ON_STACK__:
  Die Ergebnisse von Funktionen werden auf dem Stack bergeben, sonst
  in Registern (D0/D1). Default ist die bergabe in Registern.

  __LONG_WHOLE__:
  Die Typen CARDINAL und INTEGER sind identisch mit LONGCARD und
  LONGINT, also den grten Ganzzahltypen, entsprechend ISO, sonst
  mit SHORTCARD und SHORTINT. Per Default mit den LONG-Typen identisch.

  __LONG_REAL__:
  Der Typ REAL ist identisch mit LONGREAL, sonst mit SHORTREAL.
  Per Default mit SHORTREAL identisch.

  __REG_VARS__:
  Lokale Variablen, die mit dem Attribut __REG__ versehen sind, werden
  als Registervariablen deklariert, sonst nicht. Defaultmig aktiviert.

  __RANGE_CODE__:
  Wenn im Quelltext das Makro __DEBUG__ auftaucht, werden die
  Compileroptionen zur Erzeugung von Index- und Bereichstests und
  hnlichem ein- bzw. ausgeschaltet. Defaultmig ausgeschaltet.

  __STACK_CODE__:
  Wie oben, es betrifft jedoch die Erzeugung von Stacktests.
  Defaultmig ausgeschaltet.

  __DEBUG_CODE__:
  Wie oben, betrifft jedoch die Erzeugung zustzlichen Codes fr die
  Untersttzung von Debuggern. Defaultmig ausgeschaltet.


Dabei ist zu bemerken, da der Stacktest i.allg. ausgeschaltet bleiben
sollte, ebenso wie der Debug- und Rangecheck-Code, da es sonst, abhngig
vom jeweiligen Compiler, zu Fehlern kommen kann.


Eine weitere Einstellung betrifft lediglich den Megamax-Compiler. Wenn
die Version 4.3c verwendet wird, mu das Makro MM2_43c durch ndern der
0 in eine 1 aktiviert werden, da sonst durch einen Compilerfehler bei den
Value-Constructors einige Module nicht bersetzt werden knnen:

  #if 0 && (defined MM2)
  #  define MM2_43c
  #endif


Vor allem beim Hnisch-Compiler kann es ntig sein, weitere Einstellungen zu
ndern: In letzter Zeit wurden einige ISO-Features in den Compiler
eingebaut, deren Bercksichtigung mit bestimmten Makros (ISO_*) ein- oder
ausgeschaltet werden kann. Welche das sind, steht in COMPILER.TXT.
Die Defaulteinstellung ist fr meine Compilerversion geeignet. Angaben
darber, welche Version welche Features untersttzt, kann ich leider nicht
machen, das mu man selber ausprobieren. Wer auf Nummer sicher gehen will,
schaltet alle in COMPILER.TXT erwhnten Makros aus.


Neben den Einstellungen in PORTAB.M2H knnen ein paar weitere direkt in
den Modulen vorgenommen werden. Die Konfiguration erfolgt ebenfalls, indem
bestimmte Makros, die am Anfang der Datei stehen, definiert werden oder
nicht. Hierzu mu die Bedingung des umgebenden #if-Ausdrucks auf 1 oder 0
gesetzt werden.

Folgende Makros existieren:

Makroname                       Modul(e)

__OSCALLS__                     OSCALLS

  Eine Definition dieses Makros fhrt lediglich dazu, da bei einigen
  Compilern die Stackkorrektur nach einem Betriebssystemaufruf entfllt,
  da dies mit dem Prozedurende automatisch geschieht. Dieses Makro wird
  in OSCALLS.M2H ausgewertet und sollte normalerweise auf das Modul OSCALLS
  beschrnkt bleiben.


LPR_LTL_MTERM                   DosSystem

  Wie in COMPILER.TXT beschrieben, mssen beim LPR-Compiler zwei Versionen
  des Moduls 'DosSystem' erzeugt werden, da die Modulterminierung innerhalb
  der Shell und bei gelinkten Programmen grundstzlich unterschiedlich ist.
  Bei der Version fr die Shell wird das Makro definiert, bei der fr die
  gelinkten Programme nicht.


__USE_SYSBASE_FOR_BASEPAGE__    DosSystem

  Mit diesem Makro kann eingestellt werden, ob der Wert der Variable BASEP
  bei Programmstart durch ein systemspezifisches Modul oder die Funktion
  "ActBasepage()" ermittelt wird. Die systemspezifischen Module liefern
  meistens den Wert, der bei Programmstart als Parameter auf dem Stack
  bergeben wird, whrend "ActBasepage()" den Wert ber eine Systemvariable
  oder einen GEMDOS-Aufruf, sofern vorhanden, ermittelt. Zwischen den beiden
  Methoden sollte eigentlich kein Unterschied bestehen, trotzdem ist die
  erste Methode die blichere.


__USE_AES_FOR_ARGV0__           args

  Als nulltes Argument der Kommandozeile eines Programms (argv[0]) wird
  normalerweise der Programmname, mit oder ohne vollstndigen Pfad,
  betrachtet. Wird zum Start eines Programms die ARGV-Methode verwendet,
  die neuer Atari-Standard ist, kann das nullte Argument ohne Probleme
  bergeben werden. Dies macht sich z.B. auch der MultiTOS-Desktop zunutze.
  Der SingleTOS-Desktop dagegen benutzt dieses Verfahren nicht, und so
  lt sich der Programmname normalerweise nicht feststellen. Wird dieses
  Makro aktiviert, wird versucht den Programmnamen ber die AES-Funktion
  shel_read zu ermitteln, was allerdings auch nicht immer funktioniert.
  Dafr meldet sich das Programm dann kurzzeitig beim AES an.
  Die benutzten AES-Funktionen sind auf die GEM-Bibliothek ``crystal''
  zugeschnitten. Das Makro ist per Default ausgeschaltet.


__NO_IO_EXCEPTIONS__            DeviceSupport, RndFile, SeqFile, StreamFile

  Die untersttzten Compiler beherrschen keine ISO-Exceptions (Ausnahmen).
  Leider knnen aber in der IO-Bibliothek Fehler nur ber Ausnahmen
  mitgeteilt werden. Eine Ausnahme fhrt in der Implementierung zu einer
  Terminierung des Programms; da dies bei Fehlern, die durch unterliegende
  Betriebssystemroutinen ausgelst wurden, wie z.B. fehlende Zugriffsrechte
  oder ein voller Datentrger, i.allg. nicht die angemessene Reaktion ist,
  kann man hiermit festlegen, da bei solchen Fehlern keine Ausnahmen
  ausgelst werden, sondern nur ein Fehlercode gesetzt wird, der dann nach
  einer IO-Operation mit der Funktion "DeviceError()" abgefragt werden kann.
  Logische Fehler, wie z.B. der Versuch auf einen Kanal zu schreiben, der
  nur zum Lesen geffnet wurde, fhren aber weiterhin zu Ausnahmen, und damit
  zum Ende des Programms, da dies Programmierfehler sind.
  Defaultmig ist dieses Makro aktiviert.


__NO_EXCEPTIONS__               RealMath, LongMath, RealXMath, LongXMath,
                                ComplexLib, LongComplexLib

  Fehler in den Argumenten der mathematischen Funktionen fhren normalerweise
  zu Ausnahmen. Mit diesem Makro kann festgelegt werden, da statt einer
  Ausnahme ein mglichst adquater Funktionswert geliefert wird. Da Fehler
  in den Argumenten i.allg. Programmierfehler sind, ist dieses Makro
  defaultmig abgeschaltet.

Die Makros __IO_EXCEPTIONS__und __NO_IO_EXCEPTIONS__ sollten in den
unterschiedlichen Modulen jeweils denselben Wert haben.


__EXP_PLUS_SIGN__               FConvBase
__EXP_UNDERFLOW__
__NO_LEADING_DIGITS__
__ONLY_EXP__

  Mit diesen Makros kann in geringem Umfang die Umwandlung zwischen
  (LONG)REAL-Zahlen und Strings gesteuert werden. Mit __EXP_PLUS_SIGN__
  wird festgelegt, ob beim Wandeln in einen String ein positiver Exponent
  ein Vorzeichen erhlt; die ISO macht darber leider widersprchliche
  Aussagen. Defaultmig wird ein Vorzeichen produziert. Mit
  __EXP_UNDERFLOW__ kann man festlegen, da bei der Umwandlung in eine
  Zahl eine zu kleine Zahl eine Ausnahme auslst, statt einfach Null zu
  liefern, wie es bei ISO angegeben ist. Mit __NO_LEADING_DIGITS__ und
  __ONLY_EXP__ kann die Syntax eines korrekten Strings fr die Umwandlung
  in eine Zahl etwas gelockert werden; dann werden auch Zahlen ohne fhrende
  Stellen vor dem Dezimalpunkt oder Zahlen, die nur aus einem Exponenten
  bestehen, akzeptiert. Da dies nicht ISO-gem ist, sind die Makros
  normalerweise abgeschaltet.


__CHECKS__                      RBTrees, DLists, Queues, Stacks, mem

  Mit diesem Makro kann festgelegt werden, ob zur Laufzeit bestimmte
  Sicherheitsabfragen vorgenommen werden. Dazu gehrt die berprfung,
  ob der bergebene ADT definiert ist, und ob die Gre der bergebenen
  Elemente mit der Definition bereinstimmt. Diese Abfragen bieten in
  der Entwicklungsphase ein zustzliches Ma an Sicherheit und knnen
  im fertigen Programm entfernt werden. Defaultmig ist dieses Makro
  aktiviert.


_DEBUG                          RBTrees, DLists, mem

  Dieses Makro ist nur fr den Test der Module selbst von Bedeutung.
  Wenn es gesetzt ist, wird Code fr einige Testprozeduren erzeugt.
  Das Makro sollte in eigenen Programmen also ausgeschaltet sein.
  Defaultmig ist es ausgeschaltet.


__MAGICLIB_TERM__               DosSystem

  Dieses Makro ist nur fr diejenigen von Bedeutung, die gleichzeitig
  die MagicLib 4.x von Peter Hellinger einsetzen. Wenn das Makro aktiviert
  ist, meldet sich ein Hauptproze bei Aufruf von "exit()" oder "Exit()"
  korrekt beim Magic-Kernel ab. Das Makro ist per Default ausgeschaltet.


__THREADSAFE__                  mem

  Wenn dieses Makro aktiviert ist, werden die Speicheranforderungen
  gleichzeitig laufender Threads korrekt behandelt. Dann mssen sich
  Threads (Prozesse) allerdings auch explizit bei der Speicherverwaltung
  an- und abmelden. Das Makro ist per Default eingeschaltet.


__USE_MEM__                     pSTORAGE

  Wenn dieses Makro aktiviert ist, wird fr Speicheranforderungen ber
  das Modul 'pSTORAGE' das Modul 'mem' benutzt, ansonsten das vom
  M2-System bereitgestellte Modul. Das Makro ist per Default ausgeschaltet.


__INCLUDE_DE_LOCALE__           loc
__INCLUDE_EN_LOCALE__
__INCLUDE_FR_LOCALE__
__INCLUDE_NL_LOCALE__

  Wenn diese Makros aktiviert werden, knnen zur Laufzeit die zugehrigen
  Locales eingestellt werde. Jedes Locale kostet allerdings Speicherplatz.
  Per Default ist nur das deutsche Locale (DE) aktiviert.


Normalerweise mssen aber die Einstellungen, sowohl die globalen in
PORTAB.M2H als auch die lokalen in den Modulen, nicht gendert werden,
da sie auf sinnnvollen Defaultwerten stehen. ndert man die Einstellungen,
sollte man sich auch der jeweiligen Auswirkungen bewut sein!


Meldungen des Prprozessors
===========================

Der Prprozessor kann whrend der Bearbeitung einige Meldungen ausgeben.
Die Meldungen drften selbsterklrend sein und bedeuten nichts Schlimmes,
sondern dienen nur der Information ber besondere Eigenschaften der
Module beim gewhlten Compiler.

Folgende Meldungen knnen auftreten:

dossyste.ipp:#warning This version of DosSystem only suitable for load-time-linking!
dossyste.ipp:#warning You need 'LPRTERMINATION' and the new 'GEMX'
dossyste.ipp:#warning You need 'CleanUp'
dossyste.ipp:#warning ...using M_Appl.ApplTerm for program termination
dossyste.ipp:#warning ...using _sysbase for determining the Basepage address
mem.ipp:#warning Storage allocation is not thread save!
args.ipp:#warning ...using AES for argv[0]
pstorage.ipp:#warning ...using 'mem' for storage allocation
pstorage.ipp:#warning ...using M2-system storage allocator


Auerdem kann der Prprozessor noch Fehlermeldungen produzieren, was
in den meisten Fllen auf eine nicht gefundene Makrodatei zurckzufhren ist.
In diesem Fall mssen die Pfade (fr PORTAB.M2H bei -imacros, und fr
OSCALLS.M2H in GNUINC) korrigiert werden.


Installation
============

Die eigentliche Installation, d.h. das bersetzen der prprozessierten
Module mit dem Compiler und das Bekanntmachen der bersetzten Dateien
mittels Suchpfaden ist systemspezifisch und deswegen in COMPILER.TXT bzw.
den Unterlagen des Modula-2-Systems beschrieben.


Tips
====

o Die Geschwindigkeit des Prprozessierens kann erhht werden, wenn hufig
  verwendete Dateien auf einem Minix-Dateisystem liegen (unter MiNT bzw.
  MultiTOS), da hier Operationen, die Dateiverzeichnisse bearbeiten (in
  diesem Fall besonders das ffnen von Dateien) erheblich schneller als auf
  einem TOS-Dateisystem ablaufen. Dies lt sich leicht selbst feststellen,
  wenn das Testprogramm 'tfile' sowohl auf einem TOS-Dateisystem als auch
  auf einem Minix-Dateisystem ausgefhrt wird; in letzterem Fall luft das
  Programm, das hauptschlich Dateien anlegt, ffnet und lscht, sichtbar
  schneller. Mindestens der Prprozessor und x2d1 sollten sich auf einem
  Minix-Dateisystem befinden, evtl. auch die Headerdatei PORTAB.M2H.

  Eine weitere Beschleunigung ist mglich, wenn mindestens die MiNT-Version
  1.10h4 verwendet wird: Da sowohl der Prprozessor als auch x2d1 mit dem
  ``shared text''-Attribut (GNU-C-Option -mbaserel) bersetzt wurden, kann
  man als Dateiattribut auf einem Minix-Dateisystem mit chmod +t <datei>
  das ``sticky bit'' setzen. Dadurch wird das Textsegment der Programme
  nur einmal in den Speicher gelesen und dann fr nachfolgende Programm-
  aufrufe weiterverwendet (wenn es zwischendurch nicht wegen Speichermangel
  entfernt wurde).

o Wegen der Menge der Dateien ist es empfehlenswert, die Bibliotheken der
  Reihe nach zu bersetzen. D.h. zuerst werden die Quelltexte aus dem POSIX-
  Verzeichnis prprozessiert und die so erzeugten Quelltexte im bersetzungs-
  verzeichnis abgelegt. Diese Dateien werden dann mithilfe der fr den
  jeweiligen Compiler vorhandenen Batchdateien bersetzt und die Objekt-
  dateien in das entsprechende Verzeichnis kopiert. Danach knnen alle
  Dateien aus dem bersetzungsverzeichnis gelscht werden. Das gleiche
  passiert dann mit den Dateien aus dem ISO-Verzeichnis und dem MISC-
  Verzeichnis. Den grten Umfang haben die POSIX-Module; um sowohl die
  Quelltexte als auch die Objektdateien in einem Verzeichnis halten zu
  knnen, sind 1.0 bis 1.5 MB erforderlich. Falls eine RAM-Disk verwendet
  wird, mu also gengend freies RAM zur Verfgung stehen, sonst mu ein
  Verzeichnis auf der Festplatte herhalten.

o Einige Modula-Compiler (Hnisch und Megamax) erlauben die Verwendung von
  Unterstrichen ('_') in Bezeichnern, die anderen jedoch nicht. Bei den
  Original-C-Bezeichnern der Module der POSIX-Bibliothek werden eine ganze
  Reihe Unterstriche verwendet ('uid_t'), die ich durch nderung der
  Namen ('uidT') ersetzt habe, um auch die anderen Compiler verwenden zu
  knnen. Wer mchte, kann jedoch auch die Originalnamen verwenden; hierfr
  gibt es eine Makrodatei C_ID.M2H, in der die genderten Bezeichner
  ber die Originalnamen definiert sind, z.B.:

    #define uidT uid_t

  Am einfachsten ist es, wenn man diese Umsetzung direkt beim Prprozessieren
  vornimmt. Zustzlich zum Einlesen der Makrodatei PORTAB.M2H wird einfach
  noch die Datei C_ID.M2H eingelesen. Es ist nur eine weitere
  Option in der Kommandozeile des Prprozessors ntig; in der Script-Datei
  des verwendeten Kommandointerpreters wird noch ein zustzliches

    -imacros <vollst. Pfad der Datei C_ID.M2H>

  eingefgt.

  Es ist allerdings auch mglich, diese Namensumsetzung nachtrglich vorzu-
  nehmen. Dazu ist ein weiterer Prprozessordurchlauf ntig, der genauso
  abluft wie der erste, nur da statt der Makrodatei PORTAB.M2H jetzt
  C_ID.M2H verwendet wird. Neben dem Namen der Makrodatei mssen in
  dem verwendeten Shell-Script noch die Endungen der zu bearbeitenden
  Quelltexte gendert werden, die ja jetzt nicht mehr auf .dpp und .ipp
  lauten.

  In einer weiteren Makrodatei M2_ID.M2H sind die Namen in der ``anderen
  Richtung'' definiert, es ist also auch mglich, von den Originalnamen
  zurck zu den genderten Bezeichnern zu kommen; dazu ist wie oben ein
  zustzlicher Prprozessordurchlauf mit nderungen am Shell-Script
  notwendig.

o An mehreren Stellen der M2LIB-Dokumentation wird die GEM-Bibliothek
  ``crystal'' erwhnt. Diese Bibliothek greift an einigen Stellen auf M2LIB
  zurck, genauer gesagt auf Module der POSIX-Bibliothek, das ist jedoch auch
  abschaltbar (per Makro). Auerdem werden sowohl in crystal als auch in
  M2LIB zwei identische Module verwendet: PORTAB und pSTORAGE. Wer sowohl
  crystal als auch M2LIB verwenden will, sollte so vorgehen, damit es nicht
  zu (Versions)Konflikten kommt: Zuerst werden alle M2LIB-Module bersetzt
  (zur Zeit reicht es auch aus, die POSIX-Module zu bersetzen), danach kann
  man die crystal-Module prprozessieren und bersetzen. Die Module PORTAB
  und pSTORAGE drfen allerdings nicht neu bersetzt werden! Ebenso mu man
  darauf verzichten, die POSIX-Module neu zu bersetzen, obwohl dafr in
  crystal auch einige Batch-Dateien vorhanden sind. Diese Vorgehensweise
  stimmt vielleicht nicht ganz mit der in der crystal-Dokumentation
  empfohlenen berein, aber zumindest ich habe damit weniger Probleme.

  Wie weiter oben erwhnt, kann man in 'args' die Ermittlung des
  Programmnamens auch ber ShelRead erledigen lassen, wobei Funktionen
  aus crystal verwendet werden. Wer das mchte, hlt sich am besten auch
  an die oben beschriebene Reihenfolge, nur da das Implementationsmodul
  von 'args' bei der bersetzung ausgespart bleibt. Dieses kann dann
  zum Schlu (nachdem crystal bersetzt wurde) separat bersetzt werden.
